/* process.c */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "process.h"
#include "log.h"
#include "ticket.h"
#include "user.h"

ticket_collection_t * tickets;
user_database_t * users;
logfile_t *logfile;

static int login(int, protocol_t *in_msg, protocol_t* out_msg,msg_sender sender);
static int query_ticket(int, protocol_t *in_msg, protocol_t* out_msg,msg_sender sender);
static int book_ticket(int, protocol_t *in_msg, protocol_t* out_msg,msg_sender sender);
static int query_booking(int, protocol_t *in_msg, protocol_t* out_msg,msg_sender sender);
static int end_session(int, protocol_t *in_msg, protocol_t* out_msg,msg_sender sender);

static business_handler process_handlers[10] = {
	NULL,
	login,
	NULL,
	book_ticket,
	NULL,
	query_ticket,
	NULL,
	query_booking,
	NULL,
	end_session
};
	
int process_action(int fd, protocol_t *in_msg, protocol_t *out_msg, msg_sender sender){
	if(in_msg->act_type <=0 || in_msg->act_type>9)
		return -1;
	else if(process_handlers[in_msg->act_type] == NULL) 
		return -1;

	empty_msg(out_msg);
	return process_handlers[in_msg->act_type](fd,in_msg, out_msg, sender);
}

int tbs_init(){

	if( tickets == NULL){
		if((tickets = ticket_collection_open("data/ticket.dat")) == NULL){
			perror("cannot open ticket database!");
			exit(-1);
		}
	}
	
	if( users == NULL){
		if((users = user_database_open("data/user.dat")) == NULL){
			perror("cannot open user database!");
			exit(-1);
		}
	}
	
	if( logfile == NULL){
		if((logfile = logfile_open("data/logs.log")) == NULL){
			perror("cannot open log file!");
			exit(-1);
		}
	}
	return 0;
}

int tbs_end(){
	ticket_collection_close(tickets);
	user_database_close(users);
	logfile_close(logfile);
	return 0;
}




static int login(int fd, protocol_t *in_msg, protocol_t* out_msg,msg_sender sender){
	int id;
	if(in_msg == NULL || out_msg == NULL ||in_msg->act_type != ASK_LOGIN)
		return -1;
	out_msg->act_type = RPL_LOGIN;
	strcpy(out_msg->usr_name, in_msg->usr_name);
	strcpy(out_msg->usr_pwd, in_msg->usr_pwd);
	
	id = check_user(users, in_msg->usr_name, in_msg->usr_pwd);

	printf("\nuser login, id = %d",id);
	if(id >= -3){
		out_msg->usr_id = id;
		return 0;
	}else 
		return -1;
}

static int query_ticket(int fd,protocol_t *in_msg, protocol_t* out_msg,msg_sender sender){
	int i;
	char buf[512];
	ticket_t *tics = tickets->tickets;
	if(in_msg == NULL || out_msg == NULL ||in_msg->act_type != ASK_QUERY_TICKET)
		return -1;
	
	if(in_msg->usr_id < 0){
		out_msg->act_type = RPL_DENY;
		return 0;
	}
	empty_msg(out_msg);
	out_msg->act_type = RPL_QUERY_TICKET;
	out_msg->usr_id = in_msg->usr_id;
	strcpy(out_msg->train_no, in_msg->train_no);
	for(i = 0; i<tickets->len; i++){
		if(strcmp(tics[i].trainno, in_msg->train_no) == 0 && 
			tics[i].time <= in_msg->time_end &&
			tics[i].time >= in_msg->time_start){
			
			strcpy(out_msg->other, tics[i].description);
			out_msg->time_start = tics[i].time;
			out_msg->ticket_id = tics[i].id;
			out_msg->ticket_count = tics[i].num;
			printf("find one ticket,  id = %d",out_msg->ticket_id);			
			format_msg(out_msg, buf);
			printf("The ticket: %s\n", buf);
			sender(fd, buf);
		}
	}
	out_msg->ticket_id = -1;
	format_msg(out_msg, buf);
	return 0;
}

static int book_ticket(int fd,protocol_t *in_msg, protocol_t* out_msg,msg_sender sender){
	int i;
	ticket_t * tics = tickets->tickets;
	if(in_msg == NULL || out_msg == NULL ||in_msg->act_type != ASK_BOOK)
		return -1;
	if(in_msg->usr_id < 0){
		out_msg->act_type = RPL_DENY;
		return 0;
	}	
	out_msg->act_type = RPL_LOGIN;
	out_msg->usr_id = in_msg->usr_id;
	printf("\nIn book ticket , count = %d\n", in_msg->ticket_count);
	for(i = 0; i<tickets->len; i++){
		if(in_msg->ticket_id == tics[i].id){
			out_msg->time_start = tics[i].time;
			out_msg->ticket_id = tics[i].id;
			strcpy(out_msg->train_no, tics[i].trainno);
			out_msg->ticket_count = in_msg->ticket_count;
			strcpy(out_msg->other, tics[i].description);
			if(tics[i].num <= 0){
				out_msg->order_no = NO_TICKET;
				return 0;
			}else if (tics[i].num<in_msg->ticket_count){
				out_msg->order_no = LACK_TICKET;
				out_msg->ticket_count = tics[i].num;
				return 0;
			}else{	//can book
				log_t log;
				tics[i].num -=out_msg->ticket_count;
				logfile->max_order_id++;
				out_msg->order_no = logfile->max_order_id;
				
				log.order_id = logfile->max_order_id;

				log.user_id = out_msg->usr_id;
				strcpy(log.train_no, out_msg->train_no);
				strcpy(log.other, out_msg->other);
				log.time = out_msg->time_start;
				log.ticket_num = out_msg->ticket_count;
				time(&(log.order_time));
				
				add_log(logfile, &log);
				return 0;
			} 
		}	
	}
	out_msg->order_no = NO_TICKET;
	return 0;
}

static int query_booking(int fd,protocol_t *in_msg, protocol_t* out_msg,msg_sender sender){
	char buf[512];
	log_t log;
	if(in_msg == NULL || out_msg == NULL ||in_msg->act_type != ASK_QUERY_BOOKING)
		return -1;
	if(in_msg->usr_id < 0){
		out_msg->act_type = RPL_DENY;
		return 0;
	}

	empty_msg(out_msg);
	out_msg->act_type = RPL_QUERY_BOOKING;
	out_msg->usr_id = in_msg->usr_id;
	
	fseek(logfile->log_file, 0, SEEK_SET);
	while(fgets(buf,512, logfile->log_file) != NULL){
		if(parse_log(&log, buf)!= 0)
			continue;
		printf("In booking loop id=%d,id=%d \n", log.user_id, in_msg->usr_id);
		if(log.user_id == in_msg->usr_id){
			out_msg->order_no = log.order_id;
			out_msg->ticket_count = log.ticket_num;
			out_msg->time_start = log.order_time;
			out_msg->time_end = log.time;
			strcpy(out_msg->train_no, log.train_no);
			strcpy(out_msg->other, log.other);
			format_msg(out_msg, buf);
			sender(fd, buf);
		}
	}
	
	fseek(logfile->log_file, 0, SEEK_END);
	out_msg->order_no = -1;

	return 0;

}

static int end_session(int fd,protocol_t *in_msg, protocol_t* out_msg,msg_sender sender){
	return 0;
}

